package cn.bluech.lib.utils;

import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

public class FileUtils {
    private static final String TAG = "FileUtils";

    /**
     * 写文件
     * @param file 目标文件
     * @param data 要写入的数据
     * @param append 是否以追加的形式写入，如果为false将覆盖原有文件
     */
    public static boolean write(@NonNull File file, byte[] data, boolean append){
        if(file.exists()){
            if(!append)
                file.delete();
        }else {
            File parentFile = file.getParentFile();
            if(null==parentFile){
                Log.d(TAG,"File error: "+file);
                return false;
            }

            if(!parentFile.exists()){
                parentFile.mkdirs();
            }
        }

        // 写入文件
        OutputStream os = null;
        try {
            os = new FileOutputStream(file,true);
            os.write(data);
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            StreamUtils.close(os);
        }

        return true;
    }

    /**
     *
     * @param file 目标文件
     * @param is 输入流(写入完毕后不自动关闭流)
     * @param append  是否以追加的形式写入，如果为false将覆盖原有文件
     */
    public static boolean write(@NonNull File file, InputStream is, boolean append){
        if(file.exists()){
            if(!append)
                file.delete();
        }else {
            File parentFile = file.getParentFile();
            if(null==parentFile){
                Log.d(TAG,"File error: "+file);
                return false;
            }

            if(!parentFile.exists()){
                parentFile.mkdirs();
            }
        }

        // 写入文件
        OutputStream os = null;
        byte[] buf = new byte[4096];
        try {
            os = new FileOutputStream(file,true);
            while (true){
                int len = is.read(buf);
                if(len<0)
                    break;
                os.write(buf,0,len);
            }
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            StreamUtils.close(os);
        }

        return true;
    }

    /**
     * 读取整个文件，注意不要读太大的文件
     * @param file 目标文件
     * @return 文件数据
     */
    public static byte[] read(File file) {
        if((null==file)||(!file.exists()))
            return null;

        ByteArrayOutputStream bos = new ByteArrayOutputStream((int)file.length());
        InputStream is = null;

        try {
            is = new FileInputStream(file);
            byte[] buf = new byte[4096];
            while (true){
                int len = is.read(buf);
                if(len<0)
                    break;
                bos.write(buf,0,len);
            }
            return bos.toByteArray();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }finally {
            StreamUtils.close(is);
            StreamUtils.close(bos);
        }
    }

    /**
     * 写文件
     * @param filePath 文件全路径
     * @param data 要写入的数据
     * @param append 是否以追加的形式写入，如果为false将覆盖原有文件
     */
    public static boolean write(String filePath, byte[] data, boolean append){
        if(TextUtils.isEmpty(filePath)) {
            Log.d(TAG,"File path is empty");
            return false;
        }

        return write(new File(filePath),data,append);
    }

    /**
     * 写入文件，如果文件存在就覆盖原有文件
     */
    public static boolean write(String filePath, byte[] data){
        return write(filePath, data, false);
    }

    public static boolean write(File file, byte[] data){
        return write(file, data, false);
    }

    public static boolean write(File file, String str){
        return write(file, str.getBytes(), false);
    }

    public static boolean write(String filePath, String str){
        return write(new File(filePath), str.getBytes(), false);
    }

    public static boolean write(File file, InputStream is) {
        return write(file,is,false);
    }

    /**
     * 追加到文件，如果文件不存在就创建
     */
    public static boolean append(String filePath, byte[] data){
        return write(filePath, data, true);
    }

    public static boolean append(File file, byte[] data){
        return write(file, data, true);
    }

    /**
     * 文件拷贝
     */
    public static boolean write(File descFile, File srcFile) {
        InputStream is = null;
        try {
            is = new FileInputStream(srcFile);
            return write(descFile,is);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }finally {
            StreamUtils.close(is);
        }
    }

    public static byte[] read(String filePath) {
        return read(new File(filePath));
    }

    public static String readToStr(File file){
        byte[] data = read(file);
        try{
            return new String(data, Charset.forName("UTF-8"));
        }catch (Exception e){
            return null;
        }
    }

    public static String readToStr(String filePath){
        return readToStr(new File(filePath));
    }


    // 销毁文件(填充删除)
    public static boolean destroy(File file) {
        if(!file.exists())
            return false;

        long fileLength = file.length();
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);

            byte[] buf = new byte[1024];
            int count = 0;
            while (count<fileLength) {
                fos.write(buf);
                count += buf.length;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            StreamUtils.close(fos);
        }

        return file.delete();
    }

    public static boolean destroy(String filePath) {
        return destroy(new File(filePath));
    }

    /**
     * 递归删除文件/文件夹
     */
    public static boolean delete(File file) {
        if(null==file)
            return true;

        if (file.isDirectory()) {
            for (String child : file.list()) {
                boolean success = delete(new File(file, child));
                if (!success) {
                    return false;
                }
            }
        }

        return file.delete();
    }


    public static String getFileName(String filePath){
        if(TextUtils.isEmpty(filePath))
            return "";
        return new File(filePath).getName();
    }

    // 不带扩展名
    public static String getFileNameWithoutExt(String filePath){
        String name = getFileName(filePath);
        int point = name.lastIndexOf(".");
        return (point >= 0) ? name.subSequence(0, point).toString() : name;
    }
}
